/*
 * Copyright (c) 2017, Iotelligent Corporation
 * All rights reserved.
 *
 * Description:
 *
 *   RDB4 board level functions:
 *   - PA
 *   - AuxADC: Forward/Reversed Power
 *   - UART/GPIO configuration
 */

#include "ibat2000_conf.h"

/* RDB4 board hardware resource
 *
 * Ext-MCU       - NA.
 * Ext-SJC       - NA.
 * PA            - SKY65111
 * PA Bias VAPC  - AUXDAC1
 * Power Supply  - without PMIC
 * Power Enable  - External PWR_EN and RF_EN (GPIO_19)
 * Ext-LDO for VCO enable
 *               - GPIO_19
 * RST_N         - push button
 * POR_N         - push button
 * OSC_CLK2MHz   - TXC_7X_1.8432M
 * BootMode (SPI Flash)
 *               - GPIO_2 (Jumper Pull-down)
 * AuxADC0       - LM60 Temperature Sensor
 * AuxADC1       - RxIN power detect
 * AuxADC2       - FWR power detect
 * ANT_Selection - GPIO_0, 1
 * PMIC SPI      - NA.
 * power_detect_step
 *               - 30mV/Step
 */

/*
 * Board GPIO initialization
 *
 * Notice:
 * - This function shoulde be called before spi_init() as it calls GPIO reset in
 *   the GPIO configuration procedure.
 * - The chip select pin for SPI flash is also initialized here.
 */
void sys_gpio_init( void )
{
    /* Reset GPIOs */
    gpio_init();
    /* RF switch */
//    gpio_config( GPIO_ANT_V1, GPIO_MODE_OUTPUT, GPIO_INT_DISABLE, GPIO_INT_HIGH_LEVEL );
//    gpio_config( GPIO_ANT_V2, GPIO_MODE_OUTPUT, GPIO_INT_DISABLE, GPIO_INT_HIGH_LEVEL );
    /* RF Enable */
    gpio_config( GPIO_RF_EN, GPIO_MODE_OUTPUT, GPIO_INT_DISABLE, GPIO_INT_HIGH_LEVEL );
    gpio_output( GPIO_RF_EN, GPIO_DATA_HIGH );
    /* RF switch default config - ANT-4 */
    rf_ant_set_by_idx( DEFAULT_RF_ANTENNA_PORT );
    /* SPI flash CS pin - pinmux to GPIO and set it to output mode */
    sys_pin_mux( SYSCON_SPI0_CS_N_FUNSEL, SPI0_CS_PINMUX_GPIO4 );
    gpio_config( GPIO_4, GPIO_MODE_OUTPUT, GPIO_INT_DISABLE, GPIO_INT_HIGH_LEVEL );
    /* GPIO used to control boot mode */
    gpio_config( GPIO_BOOT_MODE, GPIO_MODE_OUTPUT, GPIO_INT_DISABLE, GPIO_INT_HIGH_LEVEL );
    /* Buzzer GPIO cfg and set it to quiet mode */
    sys_pin_mux( SYSCON_SPI2_CS_N_FUNSEL, SPI2_CS_PINMUX_GPIO12 );
//    gpio_config( GPIO_BUZZER, GPIO_MODE_OUTPUT, GPIO_INT_DISABLE, GPIO_INT_HIGH_LEVEL );
//    gpio_output( GPIO_BUZZER, GPIO_DATA_LOW );
}

/*
 * On RDB4, there is no individual LDO used for VDD33_VCO only, just remove the
 * function body for backward compatible.
 */

/*
 * Enable external LDO power for VCO
 */
void vco_ldo_enable( void )
{
    // gpio_output(GPIO_VCO, GPIO_DATA_HIGH);
}

/*
 * Disable external LDO power for VCO
 */
void vco_ldo_disable( void )
{
    // gpio_output(GPIO_VCO, GPIO_DATA_LOW);
}

/* Beep the buzzer */
void buzzer_on( void )
{
//    gpio_output( GPIO_BUZZER, GPIO_DATA_HIGH );
//    delay_ms( 50 );
//    gpio_output( GPIO_BUZZER, GPIO_DATA_LOW );
}

/*
 * Enable the external PA by enabling the PA Bias Current
 */
void rf_pa_enable( void )
{
    if( g_RfPara.pa_en == IOT_ENABLE )
    {
        return;
    }
    /* Set the AuxDAC1 value to 3000mV */
    analog_auxdac1_refv( g_RfPara.pa_bias );
    /* delay 100us to ensure auxdac output is stable */
    delay_us( 100 );
    g_RfPara.pa_en = IOT_ENABLE;
}

/*
 * Disable the external PA by disabling the PA Bias Current
 */
void rf_pa_disable( void )
{
    if( g_RfPara.pa_en == IOT_DISABLE )
    {
        return;
    }
    /* Set the AuxDAC1 value to 0mV */
    analog_auxdac1_refv( 0 );
    /* delay 100us to ensure auxdac output is stable */
    delay_us( 100 );
    /* insert a dummy delay to ensure tag is not energized */
    delay_us( 100 );
    g_RfPara.pa_en = IOT_DISABLE;
}

/* Gets the temperature via LM60 sensor */
void auxadc_temp_sense( float *temp )
{
    float voltage;
    auxadc_temp_sense_to_voltage( &voltage );
    /* VO = (+12.5 mV/Celsius degree * T) + 848 mV */
    *temp = ( ( voltage - 1.4 ) * 1000 - 848 ) / 12.5;
}

/*
 * Measure the Tx output power (dBm) on RF port
 *
 * - voltage
 *   The voltage measured on pin V_UP of AD8314 via AuxADC
 *
 * - tx_output
 *   The output power measured on RF port via SA
 *
 * The RF detector AD8314 is on the LO path, after measuring
 * 'voltage' and 'tx_output', we got:
 * 1) voltage = 1.2V, tx_output = 30dBm
 * 2) 30mV/dB
 *
 * Then the formular is:
 * tx_output = (voltage - 0.30f) / 0.03f + g_RfPara.tx_power_delta
 *
 * g_RfPara.tx_power_delta is a corrected value (dB) via comparing
 * tx_output and the real power measured using SA.
 */
void auxadc_rf_fwd_power( float *tx_output )
{
    float voltage;
    auxadc_rf_fwd_to_voltage( &voltage );
    //*tx_output = ( voltage - 0.10f ) / 0.03f + g_RfPara.tx_power_delta;
    *tx_output = ( voltage - 0.26f ) / 0.044f + g_RfPara.tx_power_delta;
    // TRACE_DEBUG("RF Forward Power is %.2f dBm\n", *tx_output);
}

/*
 * Measure the RxIN power (dBm) on RxIN pin of iBAT2000
 *
 * - voltage
 *   The voltage measured on pin V_UP of AD8314 via AuxADC
 *
 * - rx_input
 *   The rxin power measured on RxIN pin via SA
 *
 * The RF detector AD8314 is after the combiner which combines the power of
 * the SJC circut and the power of Rx path, after measuring 'voltage'
 * and 'rx_input', we got:
 * 1) voltage = 1.2V, rx_input = 0dBm
 * 2) 30mV/dB
 *
 * Then the formular is:
 * rx_input = (voltage - 1.20f) / 0.03f + g_RfPara.rx_power_delta
 *
 * g_RfPara.tx_power_delta is a corrected value (dB) via comparing
 * tx_output and the real power measured using SA.
 */
void auxadc_rf_rxin_power( float *rx_input )
{
    float voltage;
    auxadc_rf_rxin_to_voltage( &voltage );
    //*rx_input = ( voltage - 1.14f ) / 0.03f + g_RfPara.rx_power_delta;
    *rx_input = ( voltage - 0.46f ) / 0.044f + g_RfPara.rx_power_delta;
    // TRACE_DEBUG("RF RxIN Power is %.2f dBm\n", *rx_input);
}

#define SJC_WORK_SW     0
#define SJC_WORK_HW     1
#define SJC_WORK_MODE   SJC_WORK_HW

/* Initial sjc */
void sjc_init( void )
{
    #if (SJC_WORK_MODE == SJC_WORK_SW)
    int i_ph_read;
    int q_ph_read;
    analog_sjc_init( 1, 1, &i_ph_read, &q_ph_read );
    #else
    analog_rx_sample_hold_init( 10000, 15, 30, 0 );
    analog_tx_hold_init( 10, 1000, 10 );
    analog_sjc_init( 0, 0, NULL, NULL );
    #endif
}

/* Run internal sjc algorithm */
void sjc_start( void )
{
    ANALOG_RF_SJC_T sjc;
    float fwd_pwr, rxin_pwr;
    /* measure forward and rx_in power */
    auxadc_rf_fwd_power( &fwd_pwr );
    auxadc_rf_rxin_power( &rxin_pwr );
    /* run internal sjc algorithm */
    analog_sjc_hw( &sjc );
    /* leave 1.5ms for rx s&h */
    delay_us( 1500 );
    /* debug info */
    //    TRACE_DEBUG( "\n[Int-SJC]\n" );
    //    TRACE_DEBUG( "Fwd Power: %.2f dBm, RxIn Power: %.2f dBm\n", fwd_pwr, rxin_pwr );
    //    TRACE_DEBUG( "dc_min = %d, swap_ipn = %d, i_phase_opt = %d, swap_qpn = %d, q_phase_opt = %d\n",
    //                 sjc.dc_min_opt, sjc.ipn_opt, sjc.i_phase_opt, sjc.qpn_opt, sjc.q_phase_opt );
}

